//
//  ViewController.m
//  把录制的 caf 音频转换为 mp3
//
//  Created by 杨茂盛 on 2016/12/19.
//  Copyright © 2016年 杨茂盛. All rights reserved.
//

#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>
#import "lame.h"
@interface ViewController ()
{
    
    //音频存储的路径
    NSString *_strCAFPath;
    NSString *_strMp3Path;
    
    //录制的音频器
    AVAudioRecorder *_avRecorder;
    
    
    NSMutableArray *_arrayCAFFiles;
    NSMutableArray *_arrayMp3Files;
    
    //正在记录
    BOOL _isRecording;
    //正在转换
    BOOL _isConverting;
    
}

@property (weak, nonatomic) IBOutlet UIButton *recordBtn;
@property(nonatomic,copy)NSString*lastRecordFileName;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    //1.获取沙盒路径
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    
    //2.存储 caf 的路径和 mp3的路径
    _strCAFPath = [[NSString alloc] initWithFormat:@"%@/%@",documentsDirectory,@"CAF"];
    _strMp3Path = [[NSString alloc] initWithFormat:@"%@/%@",documentsDirectory,@"Mp3"];
    NSFileManager *fileManager = [NSFileManager defaultManager];
    
    //3.创建各自的文件夹
    [fileManager createDirectoryAtPath:_strCAFPath withIntermediateDirectories:YES attributes:nil error:nil];
    [fileManager createDirectoryAtPath:_strMp3Path withIntermediateDirectories:YES attributes:nil error:nil];
}
- (IBAction)recordAudioMp3:(id)sender {
    //用于切换按钮的两种状态 开始和暂停
    _isRecording=!_isRecording;
    //如果是暂停 意为正在录制
    if (_isRecording) {
        [self.recordBtn setTitle:@"停止" forState:UIControlStateNormal];
        //取出系统的时间
        NSDateFormatter *fileNameFormatter = [[NSDateFormatter alloc] init];
        [fileNameFormatter setDateFormat:@"yyyyMMddhhmmss"];
        //把系统时间的字符格式应用为录制文件的名称
        NSString *fileName = [fileNameFormatter stringFromDate:[NSDate date]];
        fileName = [fileName stringByAppendingString:@".caf"];
        NSString *cafFilePath = [_strCAFPath stringByAppendingPathComponent:fileName];
        //创建音频设备需要的 URL
        NSURL *cafURL = [NSURL fileURLWithPath:cafFilePath];
        NSError *error;
        NSLog(@"cafURL:%@" ,cafURL);
        //设置录制音频需要的一些参数
        NSDictionary *recordFileSettings = [NSDictionary
                                            dictionaryWithObjectsAndKeys:
                                            [NSNumber numberWithInt:AVAudioQualityMin],
                                            AVEncoderAudioQualityKey, //音频质量
                                            [NSNumber numberWithInt:16],
                                            AVEncoderBitRateKey,
                                            [NSNumber numberWithInt: 2], //声音通道,这里必须为双通道 否则无法转换为 mp3
                                            AVNumberOfChannelsKey,
                                            [NSNumber numberWithFloat:44100.0], //采样率
                                            AVSampleRateKey,
                                            nil];
        //判断音频设备是否存在
        if (!_avRecorder) {
            _avRecorder = [[AVAudioRecorder alloc] initWithURL:cafURL settings:recordFileSettings error:&error];
        }else {
            if ([_avRecorder isRecording]) {
                [_avRecorder stop];
            }
            _avRecorder=Nil;
            _avRecorder = [[AVAudioRecorder alloc] initWithURL:cafURL settings:recordFileSettings error:&error];
        }
        if (_avRecorder) {
            [_avRecorder prepareToRecord];
            _avRecorder.meteringEnabled = YES;
            [_avRecorder record];
            NSLog(@"正在录制");
            self.lastRecordFileName=fileName;
        }
        //否则设置为录制
    }else {
        [self.recordBtn setTitle:@"录制" forState:UIControlStateNormal];
        if (_avRecorder) {
            [_avRecorder stop];
            _avRecorder=Nil;
            //在录制完苹果支持的 caf 文件之后 开始转换
            [self toMp3:self.lastRecordFileName];
        }
    }
}
//转换为 mp3 格式的重要代码
- (void)toMp3:(NSString*)cafFileName
{
    NSString *cafFilePath =[_strCAFPath stringByAppendingPathComponent:cafFileName];
    
    //根据当前的时间来命名录制的名称
    NSDateFormatter *fileNameFormat=[[NSDateFormatter alloc] init];
    [fileNameFormat setDateFormat:@"yyyyMMddhhmmss"];
    NSString *mp3FileName = [fileNameFormat stringFromDate:[NSDate date]];
    mp3FileName = [mp3FileName stringByAppendingString:@".mp3"];
    NSString *mp3FilePath = [_strMp3Path stringByAppendingPathComponent:mp3FileName];
    
    //开始转换
    
    int read, write;
    //转换的源文件位置
    FILE *pcm = fopen([cafFilePath cStringUsingEncoding:1], "rb");
    //转换后保存的位置
    FILE *mp3 = fopen([mp3FilePath cStringUsingEncoding:1], "wb");
    const int PCM_SIZE = 8192;
    const int MP3_SIZE = 8192;
    short int pcm_buffer[PCM_SIZE*2];
    unsigned char mp3_buffer[MP3_SIZE];
    
    //创建这个工具类
    lame_t lame = lame_init();
    lame_set_in_samplerate(lame, 44100);
    lame_set_VBR(lame, vbr_default);
    lame_init_params(lame);
    //doWhile 循环
    do {
        read = fread(pcm_buffer, 2*sizeof(short int), PCM_SIZE, pcm);
        if (read == 0){
            //这里面的代码会在最后调用 只会调用一次
            write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);
            //NSLog(@"read0%d",write);
        }
        else{
            //这个 write 是写入文件的长度 在此区域内会一直调用此内中的代码 一直再压缩 mp3文件的大小,直到不满足条件才退出
            write = lame_encode_buffer_interleaved(lame, pcm_buffer, read, mp3_buffer, MP3_SIZE);
            
            //写入文件  前面第一个参数是要写入的块 然后是写入数据的长度 声道 保存地址
            fwrite(mp3_buffer, write, 1, mp3);
            //NSLog(@"read%d",write);
        }
    } while (read != 0);
    lame_close(lame);
    fclose(mp3);
    fclose(pcm);
}
@end
